/**
 * Created by udi on 17-7-15.
 */
'use strict';

const fs = require('./async_file');
const path = require('path');

/*

 递归处理文件,文件夹

 path 路径
 floor 层数
 handleFile 文件,文件夹处理函数

 */
Object.defineProperty(String.prototype, 'format', {
  value: function () {
    var json = arguments[0];
    var setEmptyifNo = arguments[1] || false;
    var left = arguments[2] || "{", right = arguments[3] || "}"

    return this
      .replace(left + left, String.fromCharCode(7), "g")
      .replace(right + right, String.fromCharCode(8), "g")
      .replace(new RegExp(left + "(\\w+)" + right, "g"),
        //m 是指搜索到的整个部分， 如： {id} , 而 i  是指 该部分的分组内容 ， 如 id
        function (m, i) {
          if (i in json) {
            var value = json[i];
            if (value || (value === 0) || ( value === false)) {
              return value;
            }
            else {
              return "";
            }
          }
          else if (setEmptyifNo) return "";
          else return m;
        })
      .replace(String.fromCharCode(7), left, "g")
      .replace(String.fromCharCode(8), right, "g")
      ;
  }, enumerable: false
});


//"abc,def".indexOfExt(0,true,"d","ef") === { stringIndex: 4 , matchedValue: "d", matchedIndex: 2 }
Object.defineProperty(String.prototype, 'indexOfExt', {
  value: function () {
    var ignoreCase = arguments[1] || false;
    var toFind = [];
    var findFlag = {}; //key是各个值的index，value为在整个字符串的开始匹配的位置。

    if (arguments.length == 3 && (arguments[2] instanceof Array)) {
      toFind = arguments[2];

      for (var i = 0; i < toFind.length; i++) {
        findFlag[i] = 0;
      }
    }
    else {
      for (var i = 2; i < arguments.length; i++) {
        toFind.push(arguments[i]);
        findFlag[i - 2] = 0;
      }
    }


    for (var stringIndex = arguments[0], len = this.length; stringIndex < len; stringIndex++) {
      var crrentChar = this[stringIndex];

      for (var itemIndex = 0; itemIndex < toFind.length; itemIndex++) {
        var item = toFind[itemIndex];
        var itemPos = findFlag[itemIndex];

        if (item[itemPos] !== crrentChar) {
          if (!ignoreCase || (item[itemPos].toLowerCase() !== crrentChar.toLowerCase())) {
            findFlag[itemIndex] = 0
            continue;
          }
        }

        findFlag[itemIndex]++;

        //如果匹配了。
        if (findFlag[itemIndex] == item.length) {
          return {stringIndex: stringIndex - item.length + 1, matchedValue: item, matchedIndex: itemIndex};
        }
      }
    }
    return false;
  }, enumerable: false
});


Object.defineProperty(Array.prototype, 'contains', {
  value: function (index, value) {
    if (value === undefined) {
      value = index;
      index = 0;
    }
    var isFunction = value instanceof Function;
    for (var i = 0, len = this.length; i < len; i++) {
      var item = this[i];
      if (isFunction) {
        if (value(item)) return true;
      }
      else {
        if (item == value) return true;
      }
    }
    return false;
  }, enumerable: false
});

let walk = async function (path, handleFile, isFile) {
  if (await handleFile(path, isFile || false) === false) return false;
  let files = await fs.readdirAsync(path);
  for (let item of files) {
    let tmpPath = path + '/' + item;
    let stats = await fs.statAsync(tmpPath);
    if (stats.isDirectory()) {
      await walk(tmpPath, handleFile, false);
    } else {
      if (await handleFile(tmpPath, true) === false) return false;
    }
  }
}

//递归创建
let mkdirs = async function (filePath) {

  if (fs.existsSync(filePath)) return true;

  if (mkdirs(path.resolve(filePath, "../")) == false) {
    return false;
  }

  if (await fs.mkdirAsync(filePath).catch(err => false) == false) return false;
  return true;
}


//递归监控
let watchsPath = async function (path) {
  fs.watch(path, (eventType, filename) => {
    if (filename)
      console.log(eventType + ":" + filename);
    // 输出: <Buffer ...>
  });
}

let procTag = function (content, allTagNames, language) {
  //先保留当前读言。
  var allTags = allTagNames.map(it => "<" + it + ">");
  var currentLanguageTag = "<" + language + ">";

  var allSearchTags = allTagNames.map(it => "<" + it + ">");
  allSearchTags.splice(0, 0, "<ce>", "<ce/>", "<ce ");

  var procCurrentLang = function (index, tagName) {
    var indexObj = content.indexOfExt(index, true, "</" + tagName + ">");
    if (!indexObj) return false;

    content = content.slice(0, index) + content.slice(index + tagName.length + 2, indexObj.stringIndex) + content.slice(indexObj.stringIndex + tagName.length + 3);
    return true;
  }

  var removeTag = function (index, tagName) {
    var indexObj = content.indexOfExt(index, true, "</" + tagName + ">");
    if (!indexObj) return false;

    content = content.slice(0, index) + content.slice(indexObj.stringIndex + tagName.length + 3);
    return true;
  }

  var procCeTag = function (indexObj) {

    if (indexObj.matchedIndex == 2) {
      var m = content.slice(indexObj.stringIndex).match(/^<ce\s*\/>/i)
      if (m && (m.index == 0)) {
        indexObj.matchedValue = m[0];
      }
    }

    //往前找。
    var prevFlagIndexObj = content.slice(0, indexObj.stringIndex).split("").reverse().join("").indexOfExt(0, false, ">", "'", "\"");
    if (!prevFlagIndexObj) {
      //如果找不到，则认为是在最开始。
      prevFlagIndexObj = {stringIndex: indexObj.stringIndex, matchedValue: ">", matchedIndex: 0};
    }
    var prevFlagIndex = indexObj.stringIndex - prevFlagIndexObj.stringIndex - 1;

    var nextFlagIndexObj;
    if (prevFlagIndex < 0 || content[prevFlagIndex] == ">") {
      nextFlagIndexObj = content.indexOfExt(indexObj.stringIndex + indexObj.matchedValue.length, false, "<");

      if (!nextFlagIndexObj) {
        nextFlagIndexObj = {stringIndex: content.length, matchedValue: "<", matchedIndex: 0};
      }
    }
    else {
      nextFlagIndexObj = content.indexOfExt(indexObj.stringIndex + indexObj.matchedValue.length, false, prevFlagIndexObj.matchedValue);
    }

    if (!nextFlagIndexObj) {
      return false;
    }

    var prev = content.slice(0, prevFlagIndex + 1);
    var c = content.slice(prevFlagIndex + 1, indexObj.stringIndex);
    var e = content.slice(indexObj.stringIndex + indexObj.matchedValue.length, nextFlagIndexObj.stringIndex);
    var next = content.slice(nextFlagIndexObj.stringIndex);

    if (language != "c") {
      c = "";
    }

    if (language != "e") {
      e = "";
    }

    content = prev + c + e + next;

    return true;
  }

  var prevIndex = 0;
  while (true) {
    var indexObj = content.indexOfExt(prevIndex, true, allSearchTags);
    if (!indexObj)break;

    prevIndex = indexObj.stringIndex;

    if ([0, 1, 2].indexOf(indexObj.matchedIndex) >= 0) {
      if (procCeTag(indexObj) == false) {
        prevIndex++;
      }
      continue;
    }

    if (indexObj.matchedValue == currentLanguageTag) {
      if (procCurrentLang(indexObj.stringIndex, language) == false) {
        prevIndex++;
      }
      continue;
    }

    if (removeTag(indexObj.stringIndex, allTagNames[indexObj.matchedValue]) == false) {
      prevIndex++;
    }
  }

  return content;
}

let copyFile = async function (src, target) {
  return new Promise((accept, reject) => {

    var fileWriteStream = fs.createWriteStream(target);
    fs.createReadStream(src).pipe(fileWriteStream);

    fileWriteStream.on('close', function () {
      accept();
    });
  });
}

exports.walkFile = walk;
exports.mkdirs = mkdirs;
exports.copyFile = copyFile
exports.procTagLang = procTag
exports.watchsPath = watchsPath

